package com.cabinet.ui;

import com.cabinet.Config;
import com.cabinet.SendReceiveThread;
import com.cabinet.db.*;

import javax.swing.*;
import javax.swing.event.ListSelectionEvent;
import javax.swing.event.ListSelectionListener;
import java.awt.*;
import java.awt.event.*;
import java.util.ArrayList;
import java.util.Map;


/**
 * Created by IntelliJ IDEA.
 * User: denny
 * Date: 9/16/13
 * Time: 1:44 PM
 * To change this template use File | Settings | File Templates.
 */
public class UI {
  JFrame frame;
  JDialog debugPortDialog = new DebugPortDialog(frame, "Debug");

  JMenuItem menuMoveDevices = new JCheckBoxMenuItem("Розташування", false);
  JTextArea errorLabel = new JTextArea();

  volatile DBConferenceCfg activatedDBConferenceConfig = null;

  static final String CARD_CONF = "CARD_CONF";
  static final String CARD_CLASS = "CARD_CLASS";
  static final String CARD_ERROR = "CARD_ERROR";

  CardLayout cardLayout = new CardLayout();
  ConfPanel confPanel = new ConfPanel();
  ClassPanel classPanel = new ClassPanelWithBottomConferences(){
    @Override
    void configurationSelected(int row) {
      confPanel.tblConfigs.getSelectionModel().setSelectionInterval(row, row);
      refreshConfigurationView();
      btnActivate.setEnabled( currDBConferenceCfg() != activatedDBConferenceConfig );
    }

    @Override
    void refreshConfigurationView(){
//      for( Map.Entry<Long,JList> me : conferenceLists.entrySet() ){
//        me.getValue().setModel(initConferenceJList(me.getKey()));
//      }

      Map<Long,DBDeviceState> dbDevices = currDBConferenceCfg().devStatesMap();

      for( DevicePanel dp : devicePanels.values() ){
        //dp.setDeviceName(currDBClassDeviceName(dp.devId));
        DBDeviceState state = dbDevices.get(dp.devId);
        if( state != null ){
          dp.setDeviceState(state);
        }
      }

      showbottomConferences(dbDevices);
    }


    java.util.List<String> allConfigNames(){
      java.util.List<String> ret = new ArrayList<>();
      for( DBConferenceCfg c : currDBClass().getConferenceConfigs() ){
        ret.add(c.getName());
      }
      return ret;
    }
    
    @Override
    boolean isMovingDevices() {
      return menuMoveDevices.isSelected();
    };


    @Override
    void devicesConfigChanged() {
      final DBConferenceCfg conferenceConfig = currDBConferenceCfg();
      /*
      Map<String,Long> deviceNameToConfId = new HashMap<>();
      for( Map.Entry<Long,JList> me : classPanel.conferenceLists.entrySet() ){
        Object[] all = ((DefaultListModel)me.getValue().getModel()).toArray();
        for( Object o : all ){
          deviceNameToConfId.put((String)o, me.getKey());
        }
      }
      */
      for( DBDeviceState devState : conferenceConfig.getDevStates() ){
        long conferenceId = devicePanels.get(devState.getDevId()).conferenceId;
        devState.setConferenceId(conferenceId);
        DevicePanel dpanel = devicePanels.get(devState.getDevId());
        devState.setListen(dpanel.listen.isSelected());
        devState.setSpeak(dpanel.speak.isSelected());
        devState.setSelfTest(dpanel.selftest.isSelected());
      }
      refreshConfigurationView();
      if( activatedDBConferenceConfig == conferenceConfig ){
        SendReceiveThread.INST.setConferenceConfig(activatedDBConferenceConfig);
      }

    }

    @Override
    void saveDeviceStates() {
      if( menuMoveDevices.isSelected() ){
        saveMovedDevices();
        menuMoveDevices.setSelected(false);
      }else{
        devicesConfigChanged();
        currDBSave();
      }
    }

    @Override
    void showConfigManager() {
      cardLayout.show(frame.getContentPane(), UI.CARD_CONF);
    }
  };

  private void saveMovedDevices() {
    System.out.println("saveMovedDevices()");
    DBLocations locations = new DBLocations();
    for( DevicePanel dev : classPanel.devicePanels.values() ){
      DBLocation loc = new DBLocation();
      loc.setDevId((int)dev.devId);
      loc.setX(dev.getX());
      loc.setY(dev.getY());
      locations.add(loc);
    }
    try{
      locations.save();
    }catch (Exception ex){
      ex.printStackTrace();
      showError(""+ex);
    }
  }


  public void createGUI() {

    frame = new JFrame("Лінгафонний кабінет");
    frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

    //debugPortDialog.setSize(200, 200);
    debugPortDialog.setLocation(600,200);
    debugPortDialog.pack();
    debugPortDialog.setAlwaysOnTop(true);


    Font font = new Font("Verdana", Font.PLAIN, 11);

    JMenuBar menuBar = new JMenuBar();

    JMenu fileMenu = new JMenu("Конференції");
    fileMenu.setFont(font);
    JMenu configMenu = new JMenu("Настройки");
    configMenu.add(menuMoveDevices);
    menuMoveDevices.addItemListener(new ItemListener() {
      @Override
      public void itemStateChanged(ItemEvent e) {
        if( ! menuMoveDevices.isSelected() ){
          saveMovedDevices();
        }
      }
    });

    JMenu helpMenu = new JMenu("Допомога");


    JMenu newMenu = new JMenu("New");
    newMenu.setFont(font);
    fileMenu.add(newMenu);

    JMenuItem txtFileItem = new JMenuItem("Text file");
    txtFileItem.setFont(font);
    newMenu.add(txtFileItem);

    JMenuItem imgFileItem = new JMenuItem("Image file");
    imgFileItem.setFont(font);
    newMenu.add(imgFileItem);

    JMenuItem folderItem = new JMenuItem("Folder");
    folderItem.setFont(font);
    newMenu.add(folderItem);

    JMenuItem openItem = new JMenuItem("Open");
    openItem.setFont(font);
    fileMenu.add(openItem);

    JMenuItem closeItem = new JMenuItem("Close");
    closeItem.setFont(font);
    fileMenu.add(closeItem);

    JMenuItem closeAllItem = new JMenuItem("Close all");
    closeAllItem.setFont(font);
    fileMenu.add(closeAllItem);

    fileMenu.addSeparator();

    JMenuItem exitItem = new JMenuItem("Вихід");
    exitItem.setFont(font);
    fileMenu.add(exitItem);

    exitItem.addActionListener(new ActionListener() {
      public void actionPerformed(ActionEvent e) {
        System.exit(0);
      }
    });

    menuBar.add(fileMenu);
    menuBar.add(configMenu);
    menuBar.add(helpMenu);

    frame.setJMenuBar(menuBar);

    classPanel.btnActivate.addActionListener(new ActionListener() {
      @Override
      public void actionPerformed(ActionEvent e) {
        if( !classPanel.portActivated ){
          activatedDBConferenceConfig = currDBConferenceCfg();
          classPanel.btnActivate.setText("Деактивувати");
        }else{
          activatedDBConferenceConfig=null;
          classPanel.btnActivate.setText("Активувати");
        }
        classPanel.portActivated = ! classPanel.portActivated;
        SendReceiveThread.INST.setConferenceConfig(activatedDBConferenceConfig);
      }
    });


    frame.getContentPane().setLayout(cardLayout);
    frame.getContentPane().add(classPanel, CARD_CLASS);
    frame.getContentPane().add(confPanel, CARD_CONF);
    frame.getContentPane().add(errorPanel(), CARD_ERROR);
    cardLayout.show(frame.getContentPane(), CARD_CONF);

    frame.setPreferredSize(new Dimension(700, 500));
    frame.pack();
    frame.setLocationRelativeTo(null);
    //frame.setExtendedState( frame.getExtendedState()|JFrame.MAXIMIZED_BOTH );
    frame.setSize(java.awt.Toolkit.getDefaultToolkit().getScreenSize());
    frame.setLocation(0,0);
    frame.setResizable(false);
    frame.setVisible(true);
  }

  DBClasses db(){
    return DBClasses.inst();
  }

  DBClass currDBClass(){
    int row = confPanel.tblClasses.getSelectedRow();
    DBClass dbClass = db().getClass(row);
    return dbClass;
  }

  String currDBClassDeviceName(long devId){
    return ""+devId;
    //return currDBClass().getDeviceNames().get((int)devId);
  }


  DBConferenceCfg currDBConferenceCfg(){
    int row = confPanel.tblConfigs.getSelectedRow();
    DBConferenceCfg cfg = currDBClass().getConfrenceConfig(row);
    return cfg;
  }
  
  JPanel errorPanel(){
    JPanel p = new JPanel(new BorderLayout());
    p.add(new JScrollPane(errorLabel), BorderLayout.CENTER);
    errorLabel.setForeground(Color.RED.darker());
    errorLabel.setFont(new Font("Serif", Font.BOLD, 16));
    return p;
  }
  
  void showError(String err){
    errorLabel.setText("Виникла проблема:\n"+err);
    cardLayout.show(frame.getContentPane(), CARD_ERROR);
  }
  
  class ConfPanel extends JPanel{
    JTable tblClasses;
    JTable tblDevNames;
    JTable tblConfigs;

    void stopTableEditing(){
      // preserve last uncommitted changed in edited table cells
      if (tblClasses.isEditing()){
        tblClasses.getCellEditor().stopCellEditing();
      }
      if (tblDevNames.isEditing()){
        tblDevNames.getCellEditor().stopCellEditing();
      }
      if (tblConfigs.isEditing()){
        tblConfigs.getCellEditor().stopCellEditing();
      }
    }

    ConfPanel(){
      super(new BorderLayout());
      JPanel conf = this;

      JPanel pnlEditor = new JPanel(new GridLayout(2,2, 20, 20));

      JPanel pnlClasses = new JPanel(new BorderLayout());
      JButton btnNew = new JButton("Додати");
      pnlClasses.add(btnNew, BorderLayout.NORTH);

      tblClasses = new JTable(db().getTableModel());
      tblClasses.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
      tblClasses.getSelectionModel().setSelectionInterval(0,0);
      pnlClasses.add(new JScrollPane(tblClasses), BorderLayout.CENTER);
      pnlEditor.add(pnlClasses);

      tblDevNames = new JTable();
      tblDevNames.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
      pnlEditor.add(new JScrollPane(tblDevNames));

      JPanel pnlConfigs = new JPanel(new BorderLayout());
      final JButton btnNewConfig = new JButton("Додати конфігурацію");
      pnlConfigs.add(btnNewConfig, BorderLayout.NORTH);

      tblConfigs = new JTable();
      tblConfigs.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);

      pnlConfigs.add(new JScrollPane(tblConfigs), BorderLayout.CENTER);
      pnlEditor.add(pnlConfigs);

      JPanel pnlButtons = new JPanel(new FlowLayout());
      Icon openIc = new ImageIcon(Config.getImage("open.bmp"));
      JButton btnOpen = new JButton("Відкрити", openIc);
      JButton btnSave = new JButton("Зберегти");
      pnlButtons.add(btnSave);
      pnlButtons.add(btnOpen);
      pnlEditor.add(pnlButtons);

      JLabel label = new JLabel("Оберіть (створіть) класи та конфігурації конференцій");
      label.setFont(new Font("Serif", Font.BOLD, 16));
      label.setHorizontalAlignment(SwingConstants.CENTER);
      label.setBorder(BorderFactory.createEmptyBorder(20,20,20,20));
      conf.add(label, BorderLayout.NORTH);
      conf.add(pnlEditor, BorderLayout.CENTER);

      btnNew.addActionListener(new ActionListener() {
        @Override
        public void actionPerformed(ActionEvent e) {
          stopTableEditing();
          db().addClass();
          tblClasses.getSelectionModel().setSelectionInterval(
              tblClasses.getRowCount()-1,tblClasses.getRowCount()-1);
        }
      });

      btnNewConfig.addActionListener(new ActionListener() {
        @Override
        public void actionPerformed(ActionEvent e) {
          DBClass dbClass = currDBClass();
          dbClass.addConferenceConfig();
        }
      });

      btnOpen.addActionListener(new ActionListener() {
        @Override
        public void actionPerformed(ActionEvent e) {
          int configCurrRow = tblConfigs.getSelectedRow();
          stopTableEditing();
          currDBSave();
          classPanel.refreshView();
          classPanel.configDDOptions.setSelectedIndex(configCurrRow);
          cardLayout.show(frame.getContentPane(), CARD_CLASS);
          if( Config.debugPortWindow() ){
            debugPortDialog.setVisible(true);
            //debugPortDialog.setAlwaysOnTop(true);
          }
        }
      });

      tblClasses.getSelectionModel().addListSelectionListener(new ListSelectionListener() {
        @Override
        public void valueChanged(ListSelectionEvent e) {
          refreshTblClassesSelection();
        }
      });

      btnSave.addActionListener(new ActionListener() {
        @Override
        public void actionPerformed(ActionEvent e) {
          stopTableEditing();
          currDBSave();
        }
      });
      
      refreshTblClassesSelection();
    }

    void refreshTblClassesSelection(){
      stopTableEditing();
      int row = tblClasses.getSelectedRow();
      if( tblClasses.getRowCount() > row ){
        DBClass dbClass = db().getClass(row);
        tblDevNames.setModel(dbClass.deviceNamesTabModel());
        tblConfigs.setModel(dbClass.conferenceConfigsTabModel());
        tblConfigs.getSelectionModel().setSelectionInterval(0,0);
        //btnNewConfig.setText("debug: "+row+" name="+dbClass.getName());
      }
    }
  }
  

  void currDBSave(){
    try{
      db().save();
    }catch (Exception ex){
      ex.printStackTrace();
      showError(""+ex);
    }
  }







}
